#ifdef a
#include<iostream>
using namespace std;
template<class Ab>
//A T 或其它什么均可
//加法模板
Ab Add(Ab left, Ab right) {
	return left + right;
}

//多个类型参数
//template<typename A,typename B>

template<typename T>
//交换模板
void Swap(T& left, T& right) {
	T temp = left;
	left = right;
	right = temp;
}
int main() {
	cout << Add(1,2) << endl;
	cout << Add(1.0, 2.5) << endl;
	cout << Add('1', '1') << endl;//49+49
	//cout << Add("abc", "de") << endl;//‘+’不能添加两个指针
	return  0;
}

//疑问：
//1. 加法模板对指针或者自定义类型怎么加，重载吗
//2. 一个模板类型只能用一次吗》如T/Ab
//3.不同类型
#endif

#ifdef a
#include<iostream>
using namespace std;

template<class T>//模板参数列表
T Add(const T& left, const T& right) //函数参数列表
{
	return left + right;
}

//T只能用一次，之后要重新template，上一个T编译后已经被赋予了int类型，不可作为模板
//T A(T& left,T& right) //函数参数列表
//{
//	return left + right;
//}

//Add函数模板并不是真正的函数，实例化后才成为可被调用的函数（类型参数化）
int main() {
	//隐式实例化：让编译器根据函数实参推演模板参数的实际类型
	cout << Add(1, 2) << endl;
	//显示实例化：在函数名后的<>中指定模板参数的实际类型（编译器依据指定类型进行隐式类型转化）
	//cout << Add(1, 2.0)-> 解决方式
	//1. Add(1,(int)2.0);--强制类型转换
	//2. Add<int>(1,2.0);--显示实例化
	//3.添加模板类型
	return 0;
}
//显示实例化可能进行隐式类型转换，但隐式实例化不会

//注意1：一个非模板函数可以和一个同名的函数模板同时存在，而且该函数模板还可以被实例化为这个非模板函数
//注意2：对于非模板函数和同名函数模板，如果其他条件都相同，在调动时会优先调用非模板函数而不会从该模
//		 板产生出一个实例。如果模板可以产生一个具有更好匹配的函数， 那么将选择模板

#endif


#ifdef a
//template<class T1, class T2, ..., class Tn>
//class vector	--(类模板名)
//{
//	// 类内成员定义
//};

//类模板不是类，是类的模具，真正的类是 vector<typename>
#include<iostream>
using namespace std;
template<class T>
//此处是类模板，不能使用typedef
class Stack {
private:
	T* _arr;
	size_t _capacity;
	size_t _size;
public:
	Stack()
		//:_arr(malloc(sizeof(T) * 10))
		:_arr(new T[10])
		, _capacity(10)
		, _size(0)
	{}
	~Stack() {
		if (_arr) {
			delete[] _arr;
			_capacity = 0;
			_size = 0;
		}
	}
	size_t StackCapacity()const {
		return _capacity;
	}
	T& StackTop()const {
		return _arr[_size - 1];
	}
	size_t StackSize()const {
		return _size;
	}
	void StackPush(const T& val)//常引用
	{
		//CheckCapacity;
		_arr[_size++] = val;
	}
	bool CheckEmpty()const {
		return 0 == _size;
	}
	void StackPop();
};

//类外定义法
template<class T>
void Stack<T>::StackPop() {
	if (Stack<T>::CheckEmpty())
		return;
	_size--;
}

int main() {
	Stack<int> s1;//对象创建，类的名字是 Stack<int>，而不是Stack
	s1.StackPush(1);
	s1.StackPush(2);
	s1.StackPush(3);

	cout << s1.StackTop() << endl;
	cout << s1.StackSize() << endl;
	s1.StackPop();
	s1.StackPop();
	cout << s1.StackTop() << endl;
	cout << s1.StackSize() << endl;


	Stack<double> s2;
	s2.StackPush(1.0);
	s2.StackPush(2.0);
	s2.StackPush(3.0);
	s2.StackPush(4.0);
	cout << s2.StackTop() << endl;
	cout << s2.StackSize() << endl;
	
	return 0;
}
#endif